home *** CD-ROM | disk | FTP | other *** search
- //
- // This is a patch for the Inventor 2.0 SoPointSet node, which will
- // generate incorrect normal indices when its startIndex field is not
- // zero.
- //
- // To apply this patch, compile this file into a .o and then link
- // the .o before -lInventor. The linker may give a warning.
- // This is normal and expected.
- //
-
- #include <Inventor/SoPickedPoint.h>
- #include <Inventor/SoPrimitiveVertex.h>
- #include <Inventor/actions/SoRayPickAction.h>
- #include <Inventor/details/SoPointDetail.h>
- #include <Inventor/bundles/SoMaterialBundle.h>
- #include <Inventor/bundles/SoNormalBundle.h>
- #include <Inventor/bundles/SoTextureCoordinateBundle.h>
- #include <Inventor/elements/SoComplexityElement.h>
- #include <Inventor/elements/SoGLCoordinateElement.h>
- #include <Inventor/elements/SoMaterialBindingElement.h>
- #include <Inventor/elements/SoNormalBindingElement.h>
- #include <Inventor/elements/SoNormalElement.h>
- #include <Inventor/misc/SoState.h>
- #include <Inventor/nodes/SoPointSet.h>
-
- void
- SoPointSet::generatePrimitives(SoAction *action)
- {
- // When generating primitives for picking, delay computing default
- // texture coordinates
- SbBool forPicking = action->isOfType(SoRayPickAction::getClassTypeId());
-
- SbBool materialPerPoint, normalPerPoint;
- long numPts;
- int curCoord, i;
- SoPrimitiveVertex pv;
- SoPointDetail detail;
-
- // Push state, just in case we decide to set the NormalElement
- // because we're doing auto-normal generation.
- SoState *state = action->getState();
- state->push();
- // This extra level of brackets is to make bundle constructors get
- // called before state->pop() is called:
- {
- const SoGLCoordinateElement *ce = (const SoGLCoordinateElement *)
- SoCoordinateElement::getInstance(action->getState());
-
- // Figure out number of points in set
- curCoord = (int) startIndex.getValue();
- numPts = numPoints.getValue();
- if (numPts == SO_POINT_SET_USE_REST_OF_POINTS)
- numPts = ce->getNum() - curCoord;
-
- materialPerPoint = areMaterialsPerPoint(action);
- normalPerPoint = areNormalsPerPoint(action);
-
- // Test for auto-normal case; since this modifies an element this
- // MUST BE DONE BEFORE ANY BUNDLES ARE CREATED!
- SbVec3f defaultNormal(0, 0, 1);
- const SoNormalElement *ne = SoNormalElement::getInstance(state);
- if (SoNormalBindingElement::get(state) ==
- SoNormalBindingElement::DEFAULT &&
- curCoord + numPts > ne->getNum()) {
- SoNormalElement::set(state, this, 1, &defaultNormal);
- normalPerPoint = FALSE;
- }
-
- if (forPicking)
- pv.setTextureCoords(SbVec4f(0.0, 0.0, 0.0, 0.0));
-
- pv.setDetail(&detail);
-
- SoNormalBundle nb(action, FALSE);
- SoTextureCoordinateBundle tcb(action, FALSE, ! forPicking);
-
- pv.setMaterialIndex(curCoord);
- detail.setMaterialIndex(curCoord);
-
- if (! normalPerPoint) {
- pv.setNormal(nb.get(0));
- detail.setNormalIndex(0);
- }
-
- // Get the complexity element and decide how points will be skipped
- // during processing; note that we don't want to skip anything
- // when picking.
- float cmplxValue = SoComplexityElement::get(action->getState());
- float delta = 1.8 * (0.5 - ((cmplxValue < 0.5) ? cmplxValue : 0.5));
- float fraction = 0.0;
- if (forPicking)
- delta = 0.0;
-
- for (i = 0; i < numPts; i++, fraction += delta) {
-
- // Check to see if this point should be skipped due to complexity
- if (fraction >= 1.0) {
- fraction -= 1.0;
- curCoord++;
- continue;
- }
-
- // Set coordinates, normal, and texture coordinates in
- // detail
-
- pv.setPoint(ce->get3(curCoord));
- detail.setCoordinateIndex(curCoord);
- if (normalPerPoint) {
- pv.setNormal(nb.get(curCoord));
- detail.setNormalIndex(curCoord);
- }
- if (materialPerPoint) {
- pv.setMaterialIndex(curCoord);
- detail.setMaterialIndex(curCoord);
- }
- if (tcb.isFunction()) {
- if (! forPicking)
- pv.setTextureCoords(tcb.get(pv.getPoint(),
- pv.getNormal()));
- detail.setTextureCoordIndex(0);
- }
- else {
- pv.setTextureCoords(tcb.get(curCoord));
- detail.setTextureCoordIndex(curCoord);
- }
-
- // Generate a point primitive
- invokePointCallbacks(action, &pv);
-
- curCoord++;
- }
-
- }
- state->pop(); // Restore NormalElement
- }
-